package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.page.pageResult;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    private TbSpuService spuService;

    @Autowired
    private TbBrandService brandService;

    @Autowired
    private TbCategoryService categoryService;

    @Autowired
    private TbSpuDetailService spuDetailService;

    @Autowired
    private TbSkuService skuService;

    @Override
    public pageResult<SpuDTO> findSpuByPage(Integer page, Integer rows, String key, Boolean saleable) {

        /*构造分页*/
        IPage<TbSpu> page1 = new Page<>(page,rows);
        /*构造查询条件*/
        QueryWrapper<TbSpu> queryWrapper=new QueryWrapper<>();
        /*判断处理，搜索关键*/
        if(!StringUtils.isEmpty(key)){
            queryWrapper.lambda().like(TbSpu::getName,key);
        }
        if(saleable!=null){
          /*saleable采用包装类进行参数封装*/
          queryWrapper.lambda().eq(TbSpu::getSaleable,saleable);
        }
        /*分页查询数据*/
        IPage<TbSpu> tbSpuIPage = spuService.page(page1, queryWrapper);
        /*判断数据*/
        if(tbSpuIPage==null|| CollectionUtils.isEmpty(tbSpuIPage.getRecords())){
            /*抛出异常*/
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        /*数据对象转换*/
        List<SpuDTO> spuDTOList = BeanHelper.copyWithCollection(tbSpuIPage.getRecords(), SpuDTO.class);
        /*处理品牌和分类信息*/
        handleCategoryAndBrand(spuDTOList);
        /*封装分页数据*/
        pageResult<SpuDTO> pageResult = new pageResult<>();
        pageResult.setTotalPage(tbSpuIPage.getPages());
        pageResult.setTotal(tbSpuIPage.getTotal());
        pageResult.setItems(spuDTOList);
        return pageResult;
    }

    private void handleCategoryAndBrand(List<SpuDTO> spuDTOList) {

        /*获取spu数据集合，然后遍历获取，品牌id，查询品牌*/
        for (SpuDTO spuDTO : spuDTOList) {
            Long brandId = spuDTO.getBrandId();
            /*查询品牌brandService.getById()根据id查询品牌*/
            TbBrand brand = brandService.getById(brandId);
            /*获取品牌名称，设置到spuDTO中*/
            spuDTO.setBrandName(brand.getName());
            /*分类名称数据：分类名称，分别显示一级，二级，三级,用/分割*/
            /*
            * 方式一：采用字符串拼接
            *
            * */
           /* StringBuilder stringBuilder = new StringBuilder();
            *//*cid1,cid2,cid3多级分类id，采用集合存储*//*
            List<Long> list = Arrays.asList(spuDTO.getCid1(), spuDTO.getCid2(), spuDTO.getCid3());
            *//*查询分类categoryService.listByIds(list):根据分类id，批量查询
            * 如同：sql :.......where id=? or id=? or id=? .....
            * *//*
            Collection<TbCategory> categories = categoryService.listByIds(list);
            *//*遍历分类数据，拼接分类名称*//*
            for (TbCategory category : categories) {
                if(!stringBuilder.toString().equals("")){
                    stringBuilder.append("/");
                }
                stringBuilder.append(category.getName());
            }
            spuDTO.setCategoryName(stringBuilder.toString());*/

        //  方式二
            Collection<TbCategory> categories = categoryService.listByIds(spuDTO.getCategoryIds());
            /*采用Stream流*/
            String categoryName=categories.stream().map(TbCategory::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);
        }
    }



    /*新增商品
    * 参数封装为spuDTO数据：包含 spu数据，spuDetail数据 sku数据
    * 1.基本的spu数据转为tb数据
    * 2.获取spuDetail数据转换tb,并设置与spu数据相同的主键
    * 3.获取sku数据集合，转换
    * 4.添加事务
    *
    *
    *
    *
    * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveGoods(SpuDTO spuDTO) {

        /*spu基本数据转化*/
        TbSpu tbSpu = BeanHelper.copyProperties(spuDTO, TbSpu.class);
        /*主键自增*/
        //保存数据
        boolean saveSpu = spuService.save(tbSpu);//mybatisplus保存完数据会，自动回显主键，tbSpu.getID

        if(saveSpu){
            /*获取spuDetail数据*/
            SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
            /*对象转化*/
            TbSpuDetail tbSpuDetail = BeanHelper.copyProperties(spuDetailDTO, TbSpuDetail.class);
            /*设置主键*/
            tbSpuDetail.setSpuId(tbSpu.getId());
           /*保存数据*/
            boolean saveSpuDetail = spuDetailService.save(tbSpuDetail);
            if(saveSpuDetail){
                /*获取sku集合*/
                List<SkuDTO> skuDTOList = spuDTO.getSkus();
                /*对象转化*/
                List<TbSku> tbSkuList = BeanHelper.copyWithCollection(skuDTOList, TbSku.class);

                /*遍历tbSkuList集合，设置spu_id*/
                 tbSkuList.stream().forEach(tbSku -> tbSku.setSpuId(tbSpu.getId()));
                /*批量保存*/
                boolean saveBatch = skuService.saveBatch(tbSkuList);
                if(!saveBatch){
                    throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
                }
            }else {
                throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
            }
        }else {
            /*抛出异常*/
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }


    }

     @Autowired
     private AmqpTemplate amqpTemplate;//AmqpTemplate发送RabbitMQ消息的中间件 模板
    //商品上下架
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saleableGoods(Long id, Boolean saleable) {
        /*修改商品状态：spu状态改为下架，则同时sku状态也要修改为下架
        * 修改两张表
        * spu   sku
        * spu下架，则sku必定下架
        * 此处下架的为spu数据
        * 则sku也要下架
        * */

        /*
        * 根据id更新spu
        * */
        TbSpu  tbSpu=new TbSpu();
        tbSpu.setId(id);
        tbSpu.setSaleable(saleable);
        boolean updateSpu = spuService.updateById(tbSpu);
        if(updateSpu){
            /*更改sku数据状态：根据spu_id更新数据：构造更新条件*/
            UpdateWrapper<TbSku> updateWrapper=new UpdateWrapper<>();
            updateWrapper.lambda().eq(TbSku::getSpuId,id);
            updateWrapper.lambda().set(TbSku::getEnable,saleable);
            boolean updateSku = skuService.update(updateWrapper);
            if(!updateSku){
                throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
            }
        }else {
           throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
       /*商品上下架：采用RabbitMQ发送消息，创建商品详情页面*/
       /*
       * 1.注入AMPQTemplate
       * 2. amqpTemplate.convertAndSend();发送消息
       * 参数：指定交换机，队列，routingKey,消息内容
       * 3.商品的上下架，执行不同的操作，发送不同的消息队列，内容
       *   当商品上架时，发送消息，创建商品详情页面，page-service微服务，根据spu_id创建页面
       *   哪个商品已上架，发送的消息要告诉page-service微服务，所以消息体：sup_id
       * 4.参数saleable：判断上下架，为true上架，false下架
       * 5.MQConstants工具类，指定了，交换机，routingKey，队列
       * 6.交换机：leyou
       * 7.生产者需要指定：哪个交换机，routingKey是什么,消息体内容
       * 8.监听者（消费者）需要指定：哪个交换机，routingKey是什么，routingKey绑定的哪个队列
       * */
       Long spuId=tbSpu.getId();//商品spu_id，发送的消息内容，指明哪个商品已上架
       //根据上下架的判断，指定，不同的RoutingKey  :交换机与哪个队列的绑定的关键字
       String  routingKey=saleable? MQConstants.RoutingKey.ITEM_UP_KEY:MQConstants.RoutingKey.ITEM_DOWN_KEY;
       amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME,routingKey,spuId);
    }

    @Override
    public SpuDetailDTO findSpuDetailBySpuId(Long spuId) {
        /*根据spu_id查询SpuDetail数据*/
        QueryWrapper<TbSpuDetail> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(TbSpuDetail::getSpuId,spuId);
        TbSpuDetail tbSpuDetail = spuDetailService.getOne(queryWrapper);
        /*对象转化*/
        if(tbSpuDetail==null){
            throw  new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        SpuDetailDTO spuDetailDTO = BeanHelper.copyProperties(tbSpuDetail, SpuDetailDTO.class);
        return spuDetailDTO;
    }

    @Override
    public List<SkuDTO> findSkuBySpuId(Long spuId) {

        /*根据spu_id查询sku集合数据*/
        /*构造查询条件*/
        QueryWrapper<TbSku> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(TbSku::getSpuId,spuId);
        List<TbSku> tbSkuList = skuService.list(queryWrapper);
        /*对象转化*/
        if(CollectionUtils.isEmpty(tbSkuList)){
            throw  new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        List<SkuDTO> skuDTOList = BeanHelper.copyWithCollection(tbSkuList, SkuDTO.class);

        return skuDTOList;
    }


    /*更新商品数据*/
    @Override
    public void updateGoods(SpuDTO spuDTO) {

        /*spu基本数据转换*/
        TbSpu tbSpu = BeanHelper.copyProperties(spuDTO, TbSpu.class);
        /*根据id更新数据*/
        boolean updateSpu = spuService.updateById(tbSpu);
        if(updateSpu){
            /*获取spu_detail数据*/
            SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
            /*对象转化*/
            TbSpuDetail tbSpuDetail = BeanHelper.copyProperties(spuDetailDTO, TbSpuDetail.class);
            /*不用设置主键spu_id，更新有spu_id:构造更新条件*/
           /* UpdateWrapper<TbSpuDetail> updateWrapper=new UpdateWrapper<>();
            updateWrapper.lambda().eq(TbSpuDetail::getSpuId,spuDTO.getId());
            boolean update = spuDetailService.update(tbSpuDetail, updateWrapper);
*/
           /*根据主键更新*/
            boolean updateSpuDetail = spuDetailService.updateById(tbSpuDetail);
            if(updateSpuDetail){
                /*根据spu_id删除原数据*/
                /*构造删除条件*/
                 QueryWrapper<TbSku> queryWrapper=new QueryWrapper<>();
                 queryWrapper.lambda().eq(TbSku::getSpuId,spuDTO.getId());
                boolean remove = skuService.remove(queryWrapper);
                if(remove){
                    /*获取sku集合*/
                    List<SkuDTO> skuDTOList = spuDTO.getSkus();
                    /*再次添加数据:对象转换*/
                    List<TbSku> tbSkuList = BeanHelper.copyWithCollection(skuDTOList, TbSku.class);
                    /*遍历tbSkuList集合，设置spu_id*/
                    tbSkuList.stream().forEach(tbSku -> tbSku.setSpuId(spuDTO.getId()));
                    /*批量保存数据*/
                    boolean saveBatch = skuService.saveBatch(tbSkuList);
                    if(!saveBatch){
                        throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
                    }
                }else {
                    throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
                }

            }else {
                throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
            }
        }else {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }


    }
}
